package ink.tsg.springexecutor.handler;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author geo_tsg
 * @version 1.0.0
 * @ClassName MyRejectedExecutionHandler.java
 * @Description
 * @createTime 2022-04-01
 */
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {

    /**
     * 不一定能获取到执行方法的参数
     * @param r
     * @param executor
     */
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        FutureTask task = (FutureTask)r;
        // 获取调用的方法名称(反射获取私有属性)
        try {
            Object callable = getFiled(task,"callable");
            Method userDeclaredMethod = (Method) getFiled(callable,"testDIYReject");
            String methodName = userDeclaredMethod.getName();

//            logger.info("Add task to Map, methodName: [ "  + methodName + " ]");
            System.out.println("Add task to Map, methodName: [ "  + methodName + " ]");
            //在内存中维护一个全局Map, 将策略拒绝的task放置到map中
//            Hashtable<String, List<FutureTask>> rejectTaskMap = ExecutorConfig.getRejectTaskMap();
//            if(!rejectTaskMap.containsKey(methodName)){
//                List<FutureTask> taskList = new CopyOnWriteArrayList<>();
//                rejectTaskMap.put(methodName, taskList);
//            }
//            List<FutureTask> taskList = rejectTaskMap.get(methodName);
//            taskList.add(task);
//            logger.info("MethodName : [ " + methodName + " ] taskList size : [" + taskList.size() + " ]" );
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    /**
     * @Description: 反射，通过循环父类获取field值（含private）
     * @Date: 2018/12/26 15:28
     * @Param: [c, name]
     * @Return: java.lang.Object
     **/
    private static Object getFiled(Object c, String name) throws IllegalAccessException {
        while (c != null && !c.getClass().getName().toLowerCase().equals("java.lang.object")) {
            try {
                Field field = c.getClass().getDeclaredField(name);
                field.setAccessible(true);
                return field.get(c);
            } catch (NoSuchFieldException e) {
                c = c.getClass().getSuperclass();
            }
        }
        return null;
    }
}
